﻿bob.ns.setNs('bob.utils', {

    //isUndefined - implicitly from _bob.init.js
    //isNull - implicitly from _bob.init.js
    //isUndefinedOrNull - implicitly from _bob.init.js

    isNullOrWhiteSpace: function (str, bThrowOnWrongType) {

        if (bob.utils.isUndefinedOrNull(str)) {
            return true;
        }
        if (!bob.utils.isString(str)) {
            if (bThrowOnWrongType) {
                throw new Error('Wrong argument: str.');
            }
            return false;
        }

        return !bob.string.trim(str) ? true : false;
    },

    //v.2
    clone: function (source, bDeepCopy) {
        if (bob.utils.isArray(source) || bob.utils.isObject(source)) {
            return bob.collections.extensions.select.call(source, function (index, item) {
                return bDeepCopy ? bob.utils.clone(item, bDeepCopy) : item;
            });
        }
        else if (bob.utils.isDate(source)) {
            return new Date(source.valueOf());
        }
        else {
            return source;
        }
    },

    //v.2
    extendObject: function (source, extension, bDeepCopy) {

        if (bob.utils.isUndefinedOrNull(source)) {
            throw new Error('Argument null: source');
        }
        if (!bob.utils.isUndefinedOrNull(extension)) {
            for (var member in extension) {
                source[member] = bDeepCopy ? bob.utils.clone(extension[member], bDeepCopy) : extension[member];
            }
        }

        return source;

    },

    ifUndefined: function (obj, altValue) {
        return bob.utils.isUndefined(obj) ? altValue : obj;
    },

    ifNull: function (obj, altValue) {
        return bob.utils.isNull(obj) ? altValue : obj;
    },

    ifUndefinedOrNull: function (obj, altValue) {
        return bob.utils.isUndefinedOrNull(obj) ? altValue : obj;
    },

    ifNullOrWhiteSpace: function (obj, altValue) {
        return bob.utils.isNullOrWhiteSpace(obj) ? altValue : obj;
    },

    //v3
    ifNotNumber: function (obj, altValue) {
        return bob.utils.isNumber(obj) ? obj : altValue;
    },

    //v3
    ifNotBoolean: function (obj, altValue) {
        return bob.utils.isBoolean(obj) ? obj : altValue;
    },

    //v3
    ifNotString: function (obj, altValue) {
        return bob.utils.isString(obj) ? obj : altValue;
    },

    //v3
    ifNotDate: function (obj, altValue) {
        return bob.utils.isDate(obj) ? obj : altValue;
    },

    //v3
    ifNotFunction: function (obj, altValue) {
        return bob.utils.isFunction(obj) ? obj : altValue;
    },

    //v3
    ifNotArray: function (obj, altValue) {
        return bob.utils.isArray(obj) ? obj : altValue;
    },
    
    //v3
    ifNotObject: function (obj, altValue) {
        return bob.utils.isObject(obj) ? obj : altValue;
    },

    isNumber: function (obj) {
        return (typeof (obj) === 'number')
            || (Object.prototype.toString.call(obj).indexOf('Number') > 0);
    },

    isBoolean: function (obj) {
        return (typeof (obj) === 'boolean');
    },

    isString: function (obj) {
        return (typeof (obj) === 'string')
            || (Object.prototype.toString.call(obj).indexOf('String') > 0);
    },

    isDate: function (obj) {

        if (bob.utils.isUndefinedOrNull(obj)) {
            return false;
        }

        return (Object.prototype.toString.call(obj).indexOf('Date') > 0);
    },

    isFunction: function (obj) {
        return (typeof (obj) === 'function');
    },

    isArray: function (obj) {

        if (bob.utils.isUndefinedOrNull(obj)) {
            return false;
        }
        if (bob.utils.isString(obj)) {
            return false;
        }

        if (typeof obj === 'object'
            && typeof obj.length === 'number'
            && !obj.propertyIsEnumerable('length')) {
            return true;
        }

        return false;
    },

    isObject: function (obj, bAcceptUndefined, bAcceptNull) {

        var bUndefined = bAcceptUndefined ? false : bob.utils.isUndefined(obj);
        var bNull = bAcceptNull ? false : bob.utils.isNull(obj);

        return (!bUndefined && !bNull
            && !bob.utils.isNumber(obj)
            && !bob.utils.isBoolean(obj)
            && !bob.utils.isString(obj)
            && !bob.utils.isDate(obj)
            && !bob.utils.isFunction(obj)
            && !bob.utils.isArray(obj));
    },

    equals: function (value, comparison) {
        if (arguments.length < 2) {
            return false;
        }

        if (!(typeof (value) === typeof (comparison))) {
            return false;
        }

        if (!bob.utils.isUndefinedOrNull(value) && !bob.utils.isUndefinedOrNull(comparison)) {
            return value.valueOf() === comparison.valueOf();
        }

        return value == comparison;
    },

    equalsAny: function (value, arrComparisons) {
        if (arguments.length < 2) {
            return false;
        }

        var fnAny = function (index, item) {
            return bob.utils.equals(value, item);
        };

        return bob.collections.extensions.any.call(arrComparisons, fnAny);
    },

    Lazy: function (fnCreate) {

        if (!bob.utils.isFunction(fnCreate)) {
            throw new Error('Wrong argument: fnCreate.');
        }

        var self = this;

        var _fnCreate = fnCreate;
        var _set_isValueCreated = bob.prop.namedProp(this, 'isValueCreated', false, true);
        var _value = undefined;

        this.getValue = function () {
            if (!self.get_isValueCreated()) {
                _value = _fnCreate();
                _set_isValueCreated(true);
            }
            return _value;
        };
    },

    lazyFunction: function (fnCreate) {
        return (new bob.utils.Lazy(fnCreate)).getValue;
    },

    quote: function (sValue) {
        return '"' + sValue + '"';
    },

    //v.2
    executeUsing: function (disposable, fnExecute) {
        if (!bob.utils.isObject(disposable) || !bob.utils.isFunction(disposable.dispose)) {
            throw new Error('Wrong argument: disposable.');
        }
        if (!bob.utils.isFunction(fnExecute)) {
            throw new Error('Wrong argument: fnExecute.');
        }

        try {
            return fnExecute(disposable);
        }
        finally {
            disposable.dispose();
        }
    }
});
